home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 2010 April
/
PCWorld0410.iso
/
pluginy Firefox
/
722
/
722.xpi
/
chrome
/
noscript.jar
/
content
/
noscript
/
STS.js
< prev
next >
Wrap
Text File
|
2010-02-12
|
6KB
|
233 lines
// http://lists.w3.org/Archives/Public/www-archive/2009Sep/att-0051/draft-hodges-strict-transport-sec-05.plain.html
const STS = {
enabled: true,
get db() {
delete this.db;
return this.initPersistentDB();
},
initPersistentDB: function() {
return this.db = new STSDB(STSPersistence);
},
processRequest: function(chan) {
if (this.enabled) {
var uri = chan.URI;
if (uri.schemeIs("https")) {
try {
this.db.processHeader(uri.asciiHost, chan.getResponseHeader("Strict-Transport-Security"));
} catch (e) {
try {
this.db.processHeader(uri.asciiHost, chan.getResponseHeader("X-Strict-Transport-Security"));
} catch (e) {}
}
}
}
},
isSTSURI: function(uri) {
return this.enabled && this.db.matches(uri.asciiHost);
},
enterPrivateBrowsing: function() {
try {
this.db.save();
} catch(e) {}
this.db = new STSDB(this.db);
},
exitPrivateBrowsing: function() {
this.initPersistentDB();
},
eraseDB: function() {
this.db.reset();
STSPersistence.save(this.db);
},
patchErrorPage: function(docShell, errorURI) {
// see #errors-in-secure-transport-establishment
if (!this.enabled) return;
if (!(/^about:certerror?/.test(errorURI.spec) &&
this.isSTSURI(docShell.currentURI))
) return;
Thread.delay(function() {
docShell.document.getElementById("expertContent").style.display = "none";
}, 100);
},
dispose: function() {
this.db.save();
}
};
function STSDB(source) {
this._entries = {};
if (source && source._entries) { // clone
var entries = source._entries;
for (var p in entries) {
this._entries[p] = entries[p];
}
} else {
if (source && source.load) {
this._persistence = source;
this.load();
}
}
}
STSDB.prototype = {
_persistence: null,
_dirty: false,
_saveTimer: null,
processHeader: function(host, header) {
if (DNS.isIP(host)) return;
var m = header.match(/^\s*max-age\s*=\s*(\d+)\s*(;\s*includeSubDomains)?/i);
if (!m) return;
var maxAge = parseInt(m[1]);
var includeSubDomains = !!m[2];
var expiration = Math.round(Date.now() / 1000) + maxAge;
if (host in this._entries) {
var e = this._entries[host];
if (e.expiration == expiration && e.includeSubDomains == includeSubDomains)
return;
e.expiration = expiration;
e.includeSubDomains = includeSubDomains;
} else {
this.add(new STSEntry(host, expiration, includeSubDomains));
}
this.saveDeferred();
},
add: function(entry) {
this._entries[entry.host] = entry;
},
matches: function(host, asSuperDomain) {
if (host in this._entries) {
var e = this._entries[host];
if (e.expiration >= Date.now() / 1000) {
if ((!asSuperDomain || e.includeSubDomains))
return true;
} else {
delete this._entries[host];
}
}
var dotPos = host.indexOf(".");
var lastDotPos = host.lastIndexOf(".");
if (dotPos == lastDotPos)
return false;
return this.matches(host.substring(dotPos + 1), true);
},
serialize: function() {
var lines = [], ee = this._entries;
var e;
for (var h in ee) {
e = ee[h];
lines.push([e.host, e.expiration, e.includeSubDomains ? "*" : ""].join(";"));
}
return lines.join("\n");
},
restore: function(s) {
s.split(/\s+/).forEach(function(line) {
if (line) {
var args = line.split(";");
if (args.length > 1)
this.add(new STSEntry(args[0], parseInt(args[1]), !!args[2]));
}
}, this);
},
load: function() {
if (this._persistence) {
this._persistence.load(this);
this.purgeExpired();
}
},
save: function() {
if (this._dirty && this._persistence) {
this.purgeExpired();
this._persistence.save(this);
this._dirty = false;
}
},
saveDeferred: function() {
if (this._dirty || !this._persistence) return;
this._dirty = true;
if (!this._timer) this._timer = CC["@mozilla.org/timer;1"].createInstance(CI.nsITimer);
this._timer.initWithCallback(this, 10000, CI.nsITimer.TYPE_ONE_SHOT);
},
notify: function(timer) {
this.save();
},
purgeExpired: function() {
var now = Math.round(Date.now() / 1000);
for (var h in this._entries) {
if (this._entries[h].expiration < now) delete this._entries[h];
}
},
reset: function() {
this._entries = {};
this._dirty = false;
}
};
function STSEntry(host, expiration, includeSubDomains) {
this.host = host;
this.expiration = expiration;
if (includeSubDomains) this.includeSubDomains = includeSubDomains;
}
STSEntry.prototype = {
includeSubDomains: false
};
const STSPersistence = {
get _file() {
delete this._file;
var f = CC["@mozilla.org/file/directory_service;1"].getService(
CI.nsIProperties).get("ProfD", CI.nsIFile);
f.append("NoScriptSTS.db");
return this._file = f;
},
load: function(db) {
var f = this._file;
try {
if (f.exists()) db.restore(IO.readFile(f));
} catch (e) {
dump("STS: Error loading db from " + f.path + "!" + e + "\n");
return false;
}
return true;
},
save: function(db) {
f = this._file;
try {
IO.safeWriteFile(f, db.serialize());
} catch(e) {
dump("STS: Error saving db to " + f.path + "!" + e + "\n");
return false;
}
return true;
}
};